#pragma once
#include "mq_binding.hpp"
#include "mq_exchange.hpp"
#include "mq_message.hpp"
#include "mq_msgqueue.hpp"
#include<google/protobuf/map.h>
namespace mymq
{
    class VirtualHost
    {
    public:
        using Ptr = std::shared_ptr<VirtualHost>;
        VirtualHost(const std::string &hname,const std::string &basedir, const std::string &dbfile)
        :_hname(hname),
        _emp(std::make_shared<ExchangeManager>(dbfile)),
        _mqmp(std::make_shared<MsgQueueManager>(dbfile)),
        _bmp(std::make_shared<BindingManager>(dbfile)),
        _mmp(std::make_shared<MessageManager>(basedir))
        {
            //需要注意的是使用数据库保存的数据在该管理类对象初始化时就会将数据加载到内存
            //但是消息的接口设置是需要自己进行初始化的
            //将每一条消息进行初始化
            //获取每个队列
            QueueMap mqs= _mqmp->AllQueues();
            for(auto &mq:mqs)
            {
                _mmp->InitQueueMessage(mq.first);
            }
        }
        // 声明交换机
        bool DeclareExchange(const std::string name,
                             const ExchangeType &type,
                             const bool durable,
                             const bool auto_del,
                             const google::protobuf::Map<std::string, std::string> &args)
        {
            return _emp->DeclareExchange(name,type,durable,auto_del,args);
        }
        // 删除交换机
        void DeleteExchange(const std::string &ename)
        {
            //删除交换机需要先删除与该交换机有关的绑定信息
            _bmp->removeExchangeBindings(ename);
            return _emp->DeleteExchange(ename);
        }
        // 声明消息队列
        bool DeclareMsgQueue(const std::string &name,
                             const bool durable,
                             const bool exclusive,
                             const bool auto_delete,
                             const google::protobuf::Map<std::string, std::string> &args)
        {
            _mmp->InitQueueMessage(name);
            return _mqmp->DeclareQueue(name,durable,exclusive,auto_delete,args);
        }
        // 删除消息队列
        void DeleteMsgQueue(const std::string &qname)
        {
            //需删除队列的消息，绑定信息
            _mmp->DestroyQueueMessage(qname);
            _bmp->removeMsgQueueBindings(qname);
            return _mqmp->DeleteMsgQueue(qname);
        }
        //绑定
        bool Bind(const std::string &ename,const std::string &qname,const std::string &key)
        {
            Exchange::Ptr exc = _emp->SelectExchange(ename);
            MsgQueue::Ptr mq = _mqmp->SelectQueue(qname);
            return _bmp->Bind(ename,qname,key,exc->durable&&mq->durable);
        }
        //解绑
        bool UnBind(const std::string &ename,const std::string &qname)
        {
            return _bmp->unBind(ename,qname);
        }
        //发布消息
        bool BasicPublish(const std::string &qname, BasicProperties *bp, const std::string &body)
        {
            //根据该队列是否是持久存在来决定消息是否持久存储
            MsgQueue::Ptr mq = _mqmp->SelectQueue(qname);
            if(mq.get()==nullptr)
            {
                DLOG("该队列不存在 %s",qname.c_str());
                return false;
            }
            return _mmp->Insert(qname,bp,body,mq->durable);
        }
        //订阅消息
        MessagePtr BasicConsume(const std::string &qname)
        {
            return _mmp->Front(qname);
        }
        //确认消息
        void BasicAck(const std::string &qname,const std::string &msgid)
        {
            return _mmp->Ack(qname,msgid);
        }
        
        //获取一个交换机上的所有绑定信息
        QueueBindingMap ExchangeBindings(const std::string &ename)
        {
            return _bmp->getExchangeBindings(ename);
        }
        //获取所有队列
        QueueMap AllQueues()
        {
            return _mqmp->AllQueues();
        }
        void Clear()
        {
            _emp->Clear();
            _bmp->Clear();
            _mqmp->Clear();
            _mmp->Clear();
        }
        //获取一个交换机
        Exchange::Ptr SelectExchange(const std::string &ename)
        {
            return _emp->SelectExchange(ename);
        }
        bool existsExchange(const std::string &ename)
        {
            return _emp->Exists(ename);
        }
        bool existsQueue(const std::string &qname)
        {
            return _mqmp->Exists(qname);
        }
        bool existsBinding(const std::string &ename,const std::string &qname)
        {
            return _bmp->Exists(ename,qname);
        }
    private:
        std::string _hname;
        ExchangeManager::Ptr _emp; // 交换机管理句柄
        BindingManager::Ptr _bmp;  // 绑定信息管理句柄
        MsgQueueManager::Ptr _mqmp; // 消息队列管理句柄
        MessageManager::Ptr _mmp;  // 消息管理句柄
    };
}